package com.imut.lagain.filter;

import com.imut.lagain.service.IUserRoleService;
import com.imut.lagain.util.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * JWT认证过滤器
 * 用于验证请求中的JWT令牌并设置安全上下文
 */
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private static final Logger log = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
    
    private final JwtUtil jwtUtil;
    private final IUserRoleService userRoleService;
    
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_PREFIX = "Bearer ";
    
    public JwtAuthenticationFilter(JwtUtil jwtUtil, IUserRoleService userRoleService) {
        this.jwtUtil = jwtUtil;
        this.userRoleService = userRoleService;
    }
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        
        log.info("=== JWT过滤器开始处理请求 ===");
        log.info("请求方法: {}", request.getMethod());
        log.info("请求URI: {}", request.getRequestURI());
        log.info("查询字符串: {}", request.getQueryString());
        log.info("完整URL: {}", request.getRequestURL());
        log.info("远程地址: {}", request.getRemoteAddr());
        log.info("远程主机: {}", request.getRemoteHost());
        log.info("远程端口: {}", request.getRemotePort());
        
        String token = extractTokenFromRequest(request);
        log.info("从请求头中提取JWT令牌: token={}", token != null ? "存在" : "不存在");
        
        if (token != null && jwtUtil.validateToken(token)) {
            log.info("令牌存在且有效，设置认证上下文");
            
            // 从令牌中获取用户信息
            log.info("从令牌中获取用户信息");
            String openId = jwtUtil.getOpenIdFromToken(token);
            Long userId = jwtUtil.getUserIdFromToken(token);
            log.info("解析令牌得到: openId={}, userId={}", openId, userId);
            
            // 检查用户信息是否完整
            if (userId != null) {
                log.info("用户信息有效，创建认证对象");
                // 即使openId为null，只要userId存在就认为是有效认证
                UsernamePasswordAuthenticationToken authentication = 
                    new UsernamePasswordAuthenticationToken(userId, null, Collections.emptyList());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
                log.info("认证上下文设置完成");
            } else {
                log.warn("令牌中用户信息不完整: openId={}, userId={}", openId, userId);
            }
        } else {
            log.info("令牌不存在或无效");
        }
        
        log.info("继续过滤器链");
        filterChain.doFilter(request, response);
        log.info("=== JWT过滤器处理完成 ===");
    }
    
    /**
     * 从请求中提取JWT令牌
     * @param request HTTP请求
     * @return JWT令牌，如果不存在则返回null
     */
    private String extractTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
        log.debug("从请求头中获取Authorization: {}", bearerToken);
        
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(BEARER_PREFIX)) {
            String token = bearerToken.substring(BEARER_PREFIX.length());
            log.debug("提取到JWT令牌前缀");
            return token;
        }
        log.debug("未找到有效的Bearer令牌");
        return null;
    }
    
    /**
     * 获取用户权限
     * @param userId 用户ID
     * @return 权限列表
     */
    private List<SimpleGrantedAuthority> getAuthorities(Long userId) {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        
        try {
            log.info("默认给所有用户USER角色");
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            
            log.info("根据用户角色添加相应权限");
            if (userRoleService.isAdmin(userId)) {
                authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
                log.debug("为用户添加ADMIN角色: {}", userId);
            } else if (userRoleService.isPartner(userId)) {
                authorities.add(new SimpleGrantedAuthority("ROLE_PARTNER"));
                log.debug("为用户添加PARTNER角色: {}", userId);
            }
            
        } catch (Exception e) {
            log.error("获取用户权限失败: userId={}, error={}", userId, e.getMessage(), e);
            log.info("发生异常时返回默认权限");
            return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
        }
        
        return authorities;
    }
    
    /**
     * 判断是否为管理员
     * @param userId 用户ID
     * @return 是否为管理员
     */
    private boolean isAdmin(Long userId) {
        try {
            boolean result = userRoleService.isAdmin(userId);
            log.debug("检查用户是否为管理员: userId={}, result={}", userId, result);
            return result;
        } catch (Exception e) {
            log.error("检查管理员状态失败: userId={}, error={}", userId, e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 判断是否为合作伙伴
     * @param userId 用户ID
     * @return 是否为合作伙伴
     */
    private boolean isPartner(Long userId) {
        try {
            boolean result = userRoleService.isPartner(userId);
            log.debug("检查用户是否为合作伙伴: userId={}, result={}", userId, result);
            return result;
        } catch (Exception e) {
            log.error("检查合作伙伴状态失败: userId={}, error={}", userId, e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        String path = request.getRequestURI();
        String method = request.getMethod();
        
        log.info("=== 检查请求是否需要跳过JWT验证 ===");
        log.info("请求方法: {}", method);
        log.info("请求路径: {}", path);
        
        boolean shouldSkip = path.startsWith("/api/auth/") ||
               path.startsWith("/api/phone-auth/") ||
               path.startsWith("/files/") ||
               path.startsWith("/capsules/share/") ||
               path.equals("/error") ||
               path.startsWith("/actuator/") ||
               path.startsWith("/swagger-ui/") ||
               path.startsWith("/v3/api-docs/") ||
               path.equals("/favicon.ico");
        
        log.info("路径 {} 是否跳过JWT验证: {}", path, shouldSkip);
        return shouldSkip;
    }
}